
namespace("core::ClassLoader", {
	initialize : function(){
		this.readyState	= 0;
		this.status		= null;
		this.statusText	= null;
		this.headNode	= document.getElementsByTagName("head").item(0);
	},
	
	open : function( iMethod, iURL, iAsync) {
		this.method	= "GET";
		this.URL	= iURL;
	},
	
	send : function() {
		this.script = this.createScript(this.URL);
		var self   		    = this;
		var onLoad          = function() {
			self.status     = 200;
			self.statusText = "OK";
			self.readyState = 4;
			if ( self.onreadystatechange ) self.onreadystatechange();
		}
		var onReadyStateChange = function( iEvent ) {
			var e = (iEvent?iEvent:window.event).target?(iEvent?iEvent:window.event).target:(iEvent?iEvent:window.event).srcElement;
			if( e.readyState==="loaded" || e.readyState==="complete") onLoad();
		}
		if(navigator.product==="Gecko") this.script.onload = onLoad;
		else this.script.onreadystatechange = onReadyStateChange;
		
		this.headNode.appendChild(this.script);
		this.readyState = 1;
		if (this.onreadystatechange) this.onreadystatechange();
	
	},
	
	createScript : function(_src){
		var head   = document.getElementsByTagName("head").item(0);
		var scripts = head.getElementsByTagName("script");
		var script = document.createElement("script");
			script.setAttribute("type", "text/javascript");
			script.setAttribute("charset", (config.charset || "utf-8"));
			script.setAttribute("src", _src);
			return script;
	}
});


instance("core::ModuleLoader", {
	initialize : function(){
		window.cdn	  = this.cdn;
        window.toUri  = this.to_uri;
		var self	  = this;
		window.ensure = function(){self.download.apply(self,arguments)}
	},
	
	download : function(namespc, callback) {
		callback = callback || this.emptyFunc;
		(namespc instanceof Array) ?
			this.download_batch(namespc,callback): 
			this.download_only(namespc,callback);
	},
	
	download_batch : function(namespc, callback){
		var queue = namespc.slice(), self = this;
		for(var i=0; i<=namespc.length-1; i++) {
			if(this.downloaded[namespc[i]]) 
				fileloaded(namespc[i]);
			else this.download_only(namespc[i],fileloaded);
		}
		//inner helper
		function fileloaded(_ns){
			self.downloaded[_ns] = true;
			delete queue[queue.indexOf(_ns)];
			queue=queue.clean();
			(queue.length<=0)? callback():null;}
	},
	
	download_only : function(namespc, callback){
		if(this.downloaded[namespc]){return callback();}
		if(this.isloading(namespc)) {return this.queue(namespc, callback);}
		else this.queue(namespc,callback);
		
		var self = this;
        var classloaded = function(ns) {
            self.downloaded[ns] = true;
            var _callbacks = self.callbacks(ns);
            while(_callbacks && _callbacks.length > 0) {
          	   var f = _callbacks.pop();
                   f();
            }    
        };
		$(window).addEvent("classloaded", classloaded);
		var xhr = new core.ClassLoader();
		    xhr.open("GET", this.to_uri(namespc), true); 
			xhr.send();
	},
	
	to_uri : function(namespc){
		var file_path, ns  = namespc;
		var isHttpath 	   = /^(http\:\/\/|\/)(.)+/;
		var isNamespace    = /\:{2}/;
		var isControl 	   = /controls/ig;
		if(ns && isNamespace.test(ns)) {
			var parts 	   = ns.split(isNamespace);
			var classname  = parts.pop();
			var path 	   = parts.join("/");
			
			if(parts[0].toLowerCase() == "controls") {
				file_path = config.loadpaths.CONTROLS.replace(/\[classname\]/ig, classname);
			}
			else{file_path = config.loadpaths.LIBROOT + path + "/" + classname + ".js";}	
		}
		else if(ns && isHttpath.test(ns)) { file_path = ns; }
		else {file_path = config.loadpaths.LIBROOT + ns + ".js";}
		
		//CACHING?
		file_path = (isHttpath.test(file_path)) ? 
			file_path : (cdn() + "/" + file_path);
		if(config.caching.enabled == false) {
			file_path = file_path + "?time=" + new Date().getTime();}
		return file_path;
	},
	
	cdn : function(){
		var hostindex = Math.round(Math.random()*config.assethosts.development.length-1);
			hostindex = (hostindex < 0) ? 0:hostindex;
		return config.assethosts.development[hostindex] + "/";
	},
	
	queue : function(namespc,callback){
		callback = callback || this.emptyFunc;
		if(!this.download_queue[namespc]) 
			this.download_queue[namespc] = [];
		this.download_queue[namespc].push(callback);
	},
	
	isloading : function(namespc) {
		 return (this.download_queue[namespc] && this.download_queue[namespc].length > 0);
	},
	
	callbacks : function(namespc) { 
	    return this.download_queue[namespc];
    },
	emptyFunc  		: function(){},
	downloaded 		: {},
    download_queue : {}
});

//Array.prototype.remove = function(from, to) {
//  var rest = this.slice((to || from) + 1 || this.length);
//  this.length = from < 0 ? this.length + from : from;
//  return this.push.apply(this, rest);
//};

Array.prototype.clean = function(){
		    var results = [];
		    for(var i=0; i<=this.length; i++) {
		        if(!this[i]) delete this[i];
		        else results.push(this[i])
		    }
		    return results;
		};